import {
    AfterViewInit,
    Component,
    ElementRef,
    EventEmitter,
    HostListener,
    Inject,
    Input,
    OnDestroy,
    OnInit,
    Output,
    Renderer2,
    ViewChild
} from '@angular/core';
import {BaseMapComponent} from '../../../../map/base-map/base-map/base-map.component';
import {OlFeature, OlLayer, OlMap} from '../../../../map/base-map/entity/ol';
import {EventsKey} from 'ol/events';
import {DOCUMENT} from '@angular/common';
import {SysRegionTreeNodeService} from '../service/sys-region-tree-node.service';
import {RegionChangeObject, SysRegionLayerService} from '../service/sys-region-layer.service';
import {timer} from 'rxjs';
import MapBrowserEvent from 'ol/MapBrowserEvent';
import Feature from 'ol/Feature';
import Layer from 'ol/layer/Layer';
import {SysRegion, ZG} from '../entity/sys-region';
import {unByKey} from 'ol/Observable';

export interface RegionMapEvent {
    feature?: OlFeature;
    olEvent?: MapBrowserEvent;
    region?: SysRegion;
}

@Component({
    selector: 'sys-region-base-map',
    templateUrl: './sys-region-base-map.component.html',
    styleUrls: ['./sys-region-base-map.component.less']
})
export class SysRegionBaseMapComponent implements OnInit, OnDestroy, AfterViewInit {

    @ViewChild(BaseMapComponent, {static: true})
    baseMapComponent: BaseMapComponent;

    map: OlMap;
    mapElement: any;

    regionLayer: OlLayer;
    _hoverRegionFeature: OlFeature;

    pointerMoveEventKey: EventsKey;
    clickEventKey: EventsKey;

    parents: SysRegion[] = [];

    @Input()
    initRegion: SysRegion;

    mapHeight: number;

    @Input()
    container: HTMLElement;
    @ViewChild('show', {static: true})
    controrrrrr: ElementRef<any>;
    /**
     * 区划点击
     */
    @Output()
    regionClick = new EventEmitter<RegionMapEvent>();
    /**
     * 区划点击前，如果返回false直接跳出
     */
    @Input()
    beforeRegionClick: (regionMapEvent: RegionMapEvent) => boolean;
    /**
     * 区划hover
     */
    @Output()
    regionHover = new EventEmitter<RegionMapEvent>();
    /**
     * 区划hover前，如果返回false直接跳出
     */
    @Input()
    beforeRegionHover: (regionMapEvent: RegionMapEvent) => boolean;

    constructor(@Inject(DOCUMENT)
                private doc: Document,
                private elementRef: ElementRef,
                private sysRegionService: SysRegionTreeNodeService,
                private renderer2: Renderer2,
                private regionLayerService: SysRegionLayerService, ) {
    }

    @Input()
    set colors(colors) {
        this.regionLayerService.setColors(colors);
    }

    @Input()
    set labels(labels) {
        this.regionLayerService.labels = labels;
    }

    @Input()
    set defaultFontColor(value) {
        this.regionLayerService.defaultFontColor = value;
    }

    @Input()
    set defaultFillColor(value) {
        this.regionLayerService.defaultFillColor = value;
    }

    @Input()
    set defaultStrokeColor(value) {
        this.regionLayerService.defaultStrokeColor = value;
    }

    ngOnInit() {
        if (!this.initRegion) {
            this.initRegion = ZG;
        }
        this.parents = [this.initRegion];
    }

    // ngAfterContentInit(): void {
    //     debugger;
    //     if(this.container && this.controrrrrr && this.controrrrrr.nativeElement){
    //         this.renderer2.appendChild(this.container, this.controrrrrr.nativeElement);
    //     }
    // }

    ngAfterViewInit(): void {
        if (this.container && this.controrrrrr && this.controrrrrr.nativeElement) {
            this.renderer2.appendChild(this.container, this.controrrrrr.nativeElement);
        }
    }


    @HostListener('window:resize', [])
    sizeChange(): void {
        const e: HTMLElement = this.elementRef.nativeElement;
        this.mapHeight = this.doc.body.clientHeight - e.offsetTop;
        timer(100).subscribe(_ => {
            this.baseMapComponent.updateSize();
        });
    }

    baseMapInitFinish() {
        this.sizeChange();
        this.map = this.baseMapComponent.map;
        this.mapElement = this.map.getTargetElement();

        this.regionLayer = this.regionLayerService.layer;

        this.map.addLayer(this.regionLayer);

        // 添加事件
        this.regionLayerService.sourceChange.subscribe((regionChangeObject: RegionChangeObject) => {
            const extent = regionChangeObject.extent;
            if (extent && extent[0] && isFinite(extent[0])) {
                this.map.getView().fit(extent);
            }
        });

        // 添加事件
        this.pointerMoveEventKey = this.map.on('pointermove', (evt: MapBrowserEvent) => {
            const f = this.map.forEachFeatureAtPixel<OlFeature, OlFeature>(evt.pixel, (feature: Feature, layer: Layer) => {
                return this.regionLayerService.getRealHoverFeature(feature);
            }, {
                layerFilter: (layer: Layer) => {
                    return this.regionLayer === layer;
                }
            });

            if (f) {
                this.mapElement.style.cursor = 'pointer';
            } else {
                this.mapElement.style.cursor = 'auto';
            }
            if (f !== this._hoverRegionFeature) {
                if (this._hoverRegionFeature) {
                    this._hoverRegionFeature.set('highLight', false);
                }

                if (f) {
                    f.set('highLight', true);
                }
                this._hoverRegionFeature = f;

                let region = null;
                if (f) {
                    const level = f.get('level');
                    const areaName = f.get('areaName');
                    const code = f.get('code');
                    region = {level, areaName, code};
                }


                this.regionHover.emit({
                    feature: f,
                    olEvent: evt,
                    region: region
                });
            }
        });

        // 添加事件
        this.clickEventKey = this.map.on('singleclick', (evt: MapBrowserEvent) => {
            const f = this.map.forEachFeatureAtPixel<OlFeature, OlFeature>(evt.pixel, (feature: Feature, layer: Layer) => {
                return this.regionLayerService.getRealHoverFeature(feature);
            }, {
                layerFilter: (layer: Layer) => {
                    return this.regionLayer === layer;
                }
            });
            if (f) {

                const level = f.get('level');
                const areaName = f.get('areaName');
                const code = f.get('code');
                const region: SysRegion = {level, areaName, code};
                const regionMapEvent: RegionMapEvent = {
                    feature: f,
                    olEvent: evt,
                    region: region
                };

                let doNext = true;
                if (this.beforeRegionClick) {
                    doNext = !!this.beforeRegionClick(regionMapEvent);
                }

                if (doNext) {
                    this.itemClick(region, regionMapEvent);
                }
            }
        });


        this.regionChange(this.initRegion);
    }


    itemClick(region: SysRegion, regionMapEvent?: RegionMapEvent) {
        const {level} = region;
        if (level !== 'STREET' && level !== 'CUN') {
            this.parents.push(region);

            this.regionChange(region, regionMapEvent);
        }
    }


    regionBack(index) {
        this.parents = this.parents.slice(0, index + 1);
        const region = this.parents[this.parents.length - 1];
        this.regionChange(region);
    }

    regionChange(region: SysRegion, regionMapEvent?: RegionMapEvent) {
        if (region.level !== 'CUN' && region.level !== 'STREET') {
            this.regionLayerService.setByParentCode(region.code);
        }
        if (!regionMapEvent) {
            regionMapEvent = {
                region: region
            };
        }
        this.regionClick.emit(regionMapEvent);
    }

    ngOnDestroy(): void {
        if (this.map && this.regionLayer) {
            this.map.removeLayer(this.regionLayer);
            this.regionLayer = null;
        }
        if (this.clickEventKey) {
            unByKey(this.clickEventKey);
            this.clickEventKey = null;
        }
        if (this.pointerMoveEventKey) {
            unByKey(this.pointerMoveEventKey);
            this.pointerMoveEventKey = null;
        }
        this.regionLayerService.reset();
    }

}
